package com.ruoyi.recyclecomprehensive.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.security.annotation.RequiresRoles;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.recycle.domain.*;
import com.ruoyi.recycle.dto.*;
import com.ruoyi.recycle.exception.BusinessException;
import com.ruoyi.recycle.service.*;
import com.ruoyi.recycle.utils.OssUpload;
import com.ruoyi.recycle.vo.*;
import com.ruoyi.recyclecomprehensive.domain.Gift;
import com.ruoyi.recyclecomprehensive.dto.WithDrawDTO;
import com.ruoyi.recyclecomprehensive.service.GiftService;
import com.ruoyi.recyclecomprehensive.service.PersonalService;
import com.ruoyi.recyclecomprehensive.vo.ClientInfoVO;
import com.ruoyi.recyclecomprehensive.vo.GiftStatisticsVO;
import com.ruoyi.recyclecomprehensive.vo.SalesmanVO;
import com.ruoyi.system.api.RemoteUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/personalCenter")
@Api(tags = "个人中心")
@Slf4j
public class PersonalCenterController extends BaseController {
    @Autowired
    private BillRecordService billRecordService;
    @Autowired
    private PersonalService personalService;
    @Autowired
    private PriceSettingService priceSettingService;
    @Autowired
    private ISalesmanManagementService salesmanManagementService;
    @Autowired
    private IMerchantManagementService merchantManagementService;
    @Autowired
    private GiftService giftService;
    @Autowired
    private IShopManagementService shopManagementService;
    @Autowired
    private IClientUserManagementService clientUserManagementService;
    private List<String> attributes;
    private Map<String, String> roleMap;
    @Autowired
    private RemoteUserService remoteUserService;
    @Autowired
    private IHomePageSlideshowService homePageSlideshowService;
    @Autowired
    private ISysTypeConfigService sysTypeConfigService;
    @Autowired
    private ExchangeRecordService exchangeRecordService;


    @PostConstruct
    private void initAttributes() {
        attributes = new ArrayList<>();
        attributes.add("学校");
        attributes.add("餐饮");
        attributes.add("医院");
        roleMap = new HashMap<>(2);
        roleMap.put("merchant_order", "订单管理");
        roleMap.put("merchant_finance", "财务管理");
    }

    @ApiOperation("账号减碳值统计")
    @GetMapping("/recycleCategoryStatistics")
    @ApiImplicitParam(name = "merchantId", value = "综合站ID")
    public R<RecycleCategoryVO> recycleCategoryStatistics(@RequestParam Long merchantId) {
        return R.ok(personalService.recycleCategoryStatistics(merchantId));
    }

    @RequiresRoles("merchant_finance")
    @PostMapping("/billStatistics")
    @ApiOperation("我的账单统计数据")
    public R<BillRecordVO> billStatistics(@RequestBody MerchantBillRecordQueryDTO queryDTO) {
        return R.ok(billRecordService.billStatistics(queryDTO));

    }

    @RequiresRoles("merchant_finance")
    @GetMapping("/getBillRecordDetail")
    @ApiOperation("获取账单详细数据")
    @ApiImplicitParam(name = "billNo", value = "订单号")
    public R<BillRecordDetailVO> getBillRecordDetail(@RequestParam String billNo) {
        return R.ok(personalService.getBillRecordDetail(billNo));
    }

    @RequiresRoles("merchant_finance")
    @PostMapping("/queryExchangeRecord")
    @ApiOperation("查找交易记录")
    public R<List<ExchangeRecord>> queryExchangeRecord(@RequestBody MerchantBillRecordQueryDTO queryDTO) {
        return R.ok(personalService.queryExchangeRecord(queryDTO));
    }

    @RequiresRoles("merchant_finance")
    @GetMapping("/getExchangeDetail")
    @ApiOperation("获取交易记录详细数据")
    @ApiImplicitParam(name = "exchangeNo", value = "交易订单号")
    public R<ExchangeRecord> getExchangeDetail(@RequestParam String exchangeNo) {
        return R.ok(exchangeRecordService.getById(exchangeNo));
    }

    @GetMapping("/getIntegralConfigs")
    @ApiOperation("获取积分兑换规则")
    public R<IntegralConfig> getIntegralConfigs() {
        return R.ok(personalService.getIntegralConfigs());
    }

    @PostMapping("/charge")
    @ApiOperation("充值")
    @RequiresRoles("merchant_finance")
    public R<Map<String, String>> charge(@RequestBody PaymentDTO paymentDTO) {
        final Long userId = SecurityUtils.getUserId();
        return R.ok(personalService.charge(paymentDTO, userId));
    }


    @PostMapping("/payCallBack")
    public Map<String, String> payCallBack(HttpServletRequest request) {
        return personalService.payCallBack(request);
    }

    @RequiresRoles("merchant_finance")
    @PostMapping("/withDraw")
    @ApiOperation("提现申请")
    public R withDraw(@RequestBody WithDrawDTO withDrawDTO) {
        final Long userId = SecurityUtils.getUserId();
        try {
            personalService.withDraw(withDrawDTO, userId);
            return R.ok("提现成功");
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
    }

    @RequiresRoles("merchant_finance")
    @PostMapping("/addPrice")
    @ApiOperation("新增价格")
    public R<Boolean> addPrice(@RequestBody PriceSetting priceSetting) {
        return R.ok(priceSettingService.save(priceSetting));
    }

    @RequiresRoles("merchant_finance")
    @PostMapping("/queryPriceSetting")
    @ApiOperation("查询价格")
    public R<List<PriceSetting>> queryPriceSetting(@RequestBody PriceSettingQueryDTO query) {
        List<PriceSetting> defaultPrices = new ArrayList<>();
        final String category = query.getCategory();
        int i = 1;
        int x = 1;
        if (!StrUtil.containsAny(category, "家政")) {
            final List<SysTypeConfig> recyclePrices = sysTypeConfigService.list(Wrappers
                    .lambdaQuery(new SysTypeConfig()).eq(SysTypeConfig::getType, "回收分类"));
            if (CollUtil.isNotEmpty(recyclePrices)) {
                for (SysTypeConfig sc : recyclePrices) {
                    defaultPrices.add(new PriceSetting()
                            .setPrice(sc.getMoney())
                            .setCategory("回收服务").setUnit("kg")
                            .setName(sc.getName()).setSerialNumber(i));
                    i++;
                }
            }
        }
        final PriceSetting priceSetting = new PriceSetting();
        BeanUtils.copyProperties(query, priceSetting);
        List<PriceSetting> priceSettingList = priceSettingService.list(Wrappers.lambdaQuery(priceSetting));
        if (CollUtil.isNotEmpty(priceSettingList)) {
            if (CollUtil.isNotEmpty(defaultPrices)) {
                final Iterator<PriceSetting> iterator = defaultPrices.iterator();
                while (iterator.hasNext()) {
                    final PriceSetting next = iterator.next();
                    final PriceSetting existPrice = priceSettingList.stream()
                            .filter(p -> StrUtil.equals(p.getName(), next.getName()))
                            .findFirst()
                            .orElse(null);
                    if (Objects.nonNull(existPrice)) {
                        iterator.remove();
                    }
                }
                priceSettingList.addAll(defaultPrices);
                for (PriceSetting p : priceSettingList) {
                    p.setSerialNumber(x);
                    x++;
                }
            }
            return R.ok(priceSettingList);
        }
        return R.ok(defaultPrices);
    }

    @GetMapping("/getCategories")
    @ApiOperation("获取家政服务分类")
    public R<List<String>> getCategories() {
        List<String> categories = new ArrayList<>();
        final List<SysTypeConfig> houseKeepingConfigs = sysTypeConfigService.list(Wrappers.lambdaQuery(new SysTypeConfig())
                .eq(SysTypeConfig::getType, "家政分类"));
        if (CollUtil.isNotEmpty(houseKeepingConfigs)) {
            categories = houseKeepingConfigs.stream().map(SysTypeConfig::getName).collect(Collectors.toList());
        }
        return R.ok(categories);
    }

    @RequiresRoles("merchant_finance")
    @PostMapping("/editPriceSetting")
    @ApiOperation("编辑价格")
    public R<Boolean> editPriceSetting(@RequestBody PriceSetting priceSetting) {
        return R.ok(priceSettingService.updateById(priceSetting));

    }

    @PostMapping("/insertSalesman")
    @ApiOperation("添加或修改员工信息")
    public R<Boolean> insertSalesman(@RequestBody SalesmanManagement salesmanManagement) {
        try {
            if (salesmanManagement.getId() == null) {
                salesmanManagementService.save(salesmanManagement);
            } else {
                salesmanManagementService.updateById(salesmanManagement);
            }

            return R.ok(true, "添加或修改员工信息成功");
        } catch (Exception e) {
            log.error("综合站添加或修改员工信息失败,原因:{}", e.getMessage());
            return R.fail(500, "添加或修改员工信息失败");
        }
    }

    @PostMapping("/uploadFile")
    @ApiOperation("上传文件")
    public R<String> uploadFile(@RequestParam("file") MultipartFile multipartFile) {
        try {
            final String fileUrl = OssUpload.uploadFile(multipartFile, ".jpg");
            return R.ok(fileUrl);
        } catch (Exception e) {
            log.error("上传资料失败,原因:{}", e.getMessage());
            return R.fail("上传失败");
        }

    }

    @PostMapping("/querySalesmanList")
    @ApiOperation("查询员工")
    public R<List<SalesmanVO>> querySalesmanList(@RequestBody SalesmanQueryDTO queryDTO) {
        final SalesmanManagement management = new SalesmanManagement();
        BeanUtils.copyProperties(queryDTO, management);
        final List<SalesmanManagement> salesmanList = salesmanManagementService.list(Wrappers.lambdaQuery(management));
        List<SalesmanVO> list = null;
        if (CollUtil.isNotEmpty(salesmanList)) {
            salesmanList.forEach(s -> list.add(new SalesmanVO().setId(s.getId()).setSalesmanName(s.getName())
                    .setPhone(s.getPhone()).setStatus(s.getStatus())));

        }
        return R.ok(list);
    }

    @PostMapping("/bypassAccount")
    @ApiOperation("创建子账号")
    public R<Boolean> bypassAccount(@RequestBody MerchantManagement merchantManagement) {
        Boolean flag = merchantManagementService.insertMerchantManagement(merchantManagement) == 1;
        return R.ok(flag);
    }

    @PostMapping("/editPassAccount")
    @ApiOperation("编辑子账号")
    public R<Boolean> editPassAccount(@RequestBody MerchantManagement merchantManagement) {
        return R.ok(merchantManagementService.updateMerchantManagement(merchantManagement) == 1);
    }

    @PostMapping("/queryBypassAccount")
    @ApiOperation("查询子账号")
    public R<List<MerchantManagement>> queryBypassAccount(@RequestParam Long merchantId) {
        final List<MerchantManagement> list = merchantManagementService.list(Wrappers.lambdaQuery(new MerchantManagement())
                .eq(MerchantManagement::getParentId, merchantId));
        if (CollUtil.isNotEmpty(list)) {
            list.forEach(m -> {
                final R<Set<String>> roleInfos = remoteUserService.getRoleInfos(m.getUserId());

                if (roleInfos.getCode() != 200) {
                    throw new BusinessException(StrUtil.format("找不到子账号为{}的角色信息", m.getMerchantNumber()));
                }
                List<String> roles = new ArrayList<>();
                for (String roleKey : roleInfos.getData()) {
                    roles.add(roleMap.get(roleKey));
                }
                m.setRoleNames(roles);
            });

        }
        return R.ok(list);
    }

    @GetMapping("/removeBypassAccount")
    @ApiOperation("移除子账号")
    @ApiImplicitParam(name = "id", value = "综合站子账号Id")
    public R<Boolean> removeBypassAccount(@RequestParam Long id) {
        return R.ok(merchantManagementService.removeById(id));
    }

    @PostMapping("/addGift")
    @ApiOperation("添加礼品")
    public R<Boolean> addGift(@RequestBody Gift gift) {
        gift.setSum(gift.getPrice().multiply(BigDecimal.valueOf(gift.getStock())));
        return R.ok(giftService.save(gift));
    }


    @GetMapping("/queryGift")
    @ApiOperation("查询礼品列表")
    public R<List<Gift>> queryGift() {
        final String username = SecurityUtils.getUsername();
        log.info("查询礼物接口，当前用户为:{}", username);
        final MerchantManagement merchant = merchantManagementService.getOne(Wrappers.lambdaQuery(new MerchantManagement()).eq(MerchantManagement::getMerchantNumber, username));
        final Long id = merchant.getId();
        final List<Gift> gifts = giftService.list().stream().filter(g -> g.getMerchantId().equals(id)).collect(Collectors.toList());
        return R.ok(gifts);
    }

    @GetMapping("/giftStatistics")
    @ApiOperation("礼品统计")
    public R<GiftStatisticsVO> giftStatistics() {
        final String username = SecurityUtils.getUsername();
        final MerchantManagement merchant = merchantManagementService.getOne(Wrappers.lambdaQuery(new MerchantManagement()).eq(MerchantManagement::getMerchantNumber, username));
        final Long id = merchant.getId();
        return R.ok(new GiftStatisticsVO()
                .setAmount(giftService.sum(id))
                .setCount(giftService.countStock(id)));
    }

    @GetMapping("/increaseStock")
    @ApiOperation("添加礼品库存")
    @ApiImplicitParam(name = "id", value = "礼物Id")
    public R<Boolean> increaseStock(@RequestParam Long id, @RequestParam Integer number) {
        try {
            final Gift gift = giftService.getById(id);
            int increase = gift.getStock() + number;
            giftService.updateById(gift
                    .setStock(increase)
                    .setSum(gift.getPrice().multiply(BigDecimal.valueOf(increase))));
            return R.ok(true, "入库成功");

        } catch (Exception e) {
            return R.fail(false, "入库操作失败");
        }

    }

    @GetMapping("reduceStock")
    @ApiOperation("减少礼品库存")
    @ApiImplicitParam(name = "id", value = "礼物Id")
    public R<Boolean> reduceStock(@RequestParam Long id, @RequestParam Integer number) {
        try {
            final Gift gift = giftService.getById(id);
            int reduce = gift.getStock() - number;
            if (reduce < 0) {
                return R.fail("出库数量大于库存数量");
            }
            giftService.updateById(gift
                    .setStock(reduce)
                    .setSum(gift.getPrice().multiply(BigDecimal.valueOf(reduce))));
            return R.ok(true, "出库成功");

        } catch (Exception e) {
            return R.fail(false, "出库操作失败");
        }
    }

    @GetMapping("/attractRecordStatistics")
    @ApiOperation("综合站引流数据统计")
    @ApiImplicitParam(name = "merchantId", value = "综合站Id")
    public R<AttractRecordStatisticsVO> attractRecordStatistics(@RequestParam Long merchantId) {
        return R.ok(personalService.attractRecordStatistics(merchantId));

    }

    @PostMapping("/attractRecordList")
    @ApiOperation("查询平台或达人引流数据列表")
    public R<List<AttractRecordVO>> attractRecordList(@RequestBody AttractRecordQueryDTO queryDTO) {
        return R.ok(personalService.attractRecordList(queryDTO));

    }

    @GetMapping("/attractStatistics")
    @ApiOperation("达人引流数据统计")
    @ApiImplicitParam(name = "merchantId", value = "综合站ID")
    public R<AttractRecordStatisticsVO> attractClientStatistics(@RequestParam Long merchantId) {
        return R.ok(personalService.attractRecordStatistics(merchantId));

    }

    @GetMapping("/attractDataStatistics")
    @ApiOperation("引流平台或引流达人（单个）引流数据统计")
    @ApiImplicitParams({@ApiImplicitParam(name = "shopId", value = "引流平台ID,当查询引流平台数据时传递"), @ApiImplicitParam(name = "clientId", value = "客户Id，当查询引流达人数据时传递")})
    public R<AttractRecordStatisticsSingle> shopAttractStatistics(@RequestParam(required = false) Long shopId, @RequestParam(required = false) Long clientId) {
        return R.ok(personalService.attractRecordStatisticsSingle(shopId, clientId));
    }

    @PostMapping("/queryAttractDataList")
    @ApiOperation("查询引流平台或引流达人（单个）引流数据")
    public R<List<AttractDataVO>> shopDataStatistics(@RequestBody AttractDataQueryDTO dataQueryDTO) {
        return R.ok(personalService.singleDataStatistics(dataQueryDTO));
    }

    @GetMapping("/salesmanList")
    @ApiOperation("所有员工列表")
    public R<List<SalesmanVO>> salesmanList(@RequestParam Long merchantId) {
        final List<SalesmanManagement> salesmanManagements = salesmanManagementService.list(Wrappers.lambdaQuery(new SalesmanManagement())
                .eq(SalesmanManagement::getMerchantId, merchantId));
        List<SalesmanVO> list = new ArrayList<>();
        if (CollUtil.isNotEmpty(salesmanManagements)) {
            salesmanManagements.forEach(s -> {
                list.add(new SalesmanVO().setId(s.getId()).setSalesmanName(s.getName()).setPhone(s.getPhone()));
            });
        }
        return R.ok(list);
    }

    @GetMapping("/getSalesmanDetail")
    @ApiOperation("获取员工详细信息")
    @ApiImplicitParam(name = "id", value = "员工ID")
    public R<SalesmanManagement> getSalesmanDetail(@RequestParam Long id) {
        final SalesmanManagement salesman = salesmanManagementService.getById(id);
        final boolean isNull = Objects.isNull(salesman);
        return R.ok(isNull ? new SalesmanManagement() : salesman);

    }

    @GetMapping("/getShopDetail")
    @ApiOperation("获取引流平台详情")
    @ApiImplicitParam(name = "shopId", value = "引流平台Id")
    public R<ShopManagement> getShopDetail(@RequestParam Long shopId) {
        return R.ok(shopManagementService.getById(shopId) == null ? new ShopManagement() : shopManagementService.getById(shopId));
    }

    @PostMapping("/editShopDetail")
    @ApiOperation("修改引流平台详情")
    public R<Boolean> editShopDetail(@RequestBody ShopManagement shopManagement) {
        try {
            shopManagementService.updateShopManagement(shopManagement);
            return R.ok(true);
        } catch (Exception e) {
            log.error("修改门店信息错误,原因:{}", e.getMessage());
            return R.fail("修改门店信息错误");
        }

    }

    @PostMapping("/addShop")
    @ApiOperation("添加引流平台")
    public R<Boolean> addShop(@RequestBody ShopManagement shopManagement) {
        return R.ok(personalService.addShop(shopManagement));
    }

    @GetMapping("/getAttributes")
    @ApiOperation("获取平台属性")
    public R<List<String>> getAttributes() {
        return R.ok(attributes);
    }

    @GetMapping("/queryClientInfo")
    @ApiOperation("查询客户信息")
    @ApiImplicitParam(name = "clientId", value = "客户Id")
    public R<ClientInfoVO> queryClientInfo(@RequestParam Long clientId) {
        final ClientUserManagement client = clientUserManagementService.getById(clientId);
        if (client != null) {
            final Long salesmanId = client.getSalesmanId();
            final SalesmanManagement salesman = salesmanManagementService.getById(salesmanId);
            final Integer shopId = client.getShopId();
            final ShopManagement shop = shopManagementService.getById(Long.valueOf(shopId));
            final MerchantManagement merchant = merchantManagementService.getById(shop.getMerchantId());
            return R.ok(new ClientInfoVO().setAddress(client.getCity())
                    .setName(client.getUserName())
                    .setPhone(client.getPhone())
                    .setMerchant(merchant.getMerchantName())
                    .setSalesman(salesman.getName()));
        }
        return R.fail("找不到达人信息");
    }

    @ApiOperation("上传海报")
    @PostMapping("/uploadProgramCode")
    @ApiImplicitParams({@ApiImplicitParam(name = "merchantId", value = "综合站ID"), @ApiImplicitParam(name = "file", value = "推广海报")})
    public R<String> uploadProgramCode(@RequestParam(name = "merchantId") Long merchantId, @RequestParam(name = "file") MultipartFile multipartFile) {
        final String file = OssUpload.uploadFile(multipartFile, ".jpg");
        merchantManagementService.updateById(new MerchantManagement().setId(merchantId).setMiniProgramCode(file));
        return R.ok(file);

    }

    @ApiOperation("人脸识别")
    @PostMapping("/certificateIdentify")
    @ApiImplicitParams({@ApiImplicitParam(name = "idCardNo", value = "员工身份证证件号"), @ApiImplicitParam(name = "file", value = "人脸图片,图片不能大于3M"), @ApiImplicitParam(name = "name", value = "员工姓名")})
    public R<Boolean> certificateIdentify(@RequestParam("file") MultipartFile file, @RequestParam("idCardNo") String idCardNo, @RequestParam("name") String name) {
        if (file.getSize() > 3072 * 1024) {
            return R.fail("图片不能超过3MB");
        } else if (!StrUtil.equalsAnyIgnoreCase(StrUtil.subAfter(file.getOriginalFilename(), ".", false), "jpg", "png")) {
            return R.fail("仅支持图片格式为:jpg或png的图片");
        }
        return R.ok(personalService.certificateIdentify(file, idCardNo, name));

    }

    @ApiOperation("获取海报列表")
    @GetMapping("/getPosterList")
    public R<List<HomePageSlideshow>> getPosterList() {
        return R.ok(homePageSlideshowService.list(Wrappers.lambdaQuery(new HomePageSlideshow()).eq(HomePageSlideshow::getType, "5")));

    }

    @ApiOperation("获取默认海报")
    @GetMapping("/getDefaultPoster")
    public R<HomePageSlideshow> getDefaultPoster() {
        final List<HomePageSlideshow> posterList = homePageSlideshowService.list(Wrappers.lambdaQuery(new HomePageSlideshow()).eq(HomePageSlideshow::getType, "5"));
        if (CollUtil.isEmpty(posterList)) {
            return R.ok(new HomePageSlideshow().setType("5"));
        }
        return R.ok(posterList.get(0));
    }


    @ApiOperation("保存推广海报")
    @PostMapping("/savePoster")
    public R<String> savePoster(@RequestBody MerchantManagement merchantManagement) {
        merchantManagementService.updateById(merchantManagement);
        return R.ok(merchantManagement.getPoster());
    }

}
